/************************
 * HEADER
 ***********************/

#include "dominion.h"
#include "dominion_helpers.h"
#include "rngs.h"
#include "coreUnitTestHelpers.h"
#include <math.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

/* FUNCTION DEFINITIONS */
/* char *getCardName(int card); */
/* int initGame(struct gameState *G, int *k, int seed, int printMode); */
/* void printUsageStatement( /\* No Args *\/); */
 

/**************************************
 * Function getCardName()             *
 * Input: card, and String for name   *
 * Output: puts the card name in the  *
 *         given array                *
 *************************************/
char *getCardName(int card){
  if(card == curse)
    return "curse";
  else if(card == estate)
    return "estate";
  else if(card == duchy)
    return "duchy";
  else if(card == province)
    return "province";
  else if(card == copper)
    return "copper";
  else if(card == silver)
    return "silver";
  else if(card == gold)
    return "gold";
  else if(card == adventurer)
    return "adventurer";
  else if(card == council_room)
    return "council_room";
  else if(card == feast)
    return "feast";
  else if(card == gardens)
    return "gardens";
  else if(card == mine)
    return "mine";
  else if(card == remodel)
    return "remodel";
  else if(card == smithy)
    return "smithy";
  else if(card == village)
    return "village";
  else if(card == baron)
    return "baron";
  else if(card == great_hall)
    return "great_hall";
  else if(card == minion)
    return "minion";
  else if(card == steward)
    return "steward";
  else if(card == tribute)
    return "tribute";
  else if(card == ambassador)
    return "ambassador";
  else if(card == cutpurse)
    return "cutpurse";
  else if(card == embargo)
    return "embargo";
  else if(card == outpost)
    return "outpost";
  else if(card == salvager)
    return "salvager";
  else if(card == sea_hag)
    return "sea_hag";
  else if(card == treasure_map)
    return "treasure_map";
  else
    return NULL;
}


/*************************************
 * Function: initGame()              *
 * Input: gameState, array to hold   *
 *        kingdom cards              *
 * Output: returns number of players *
 *         and alters the gameState  *
 *         and kingdom card arrays   *
 ************************************/
int initGame(struct gameState *G, int *k, int seed, int printMode){
  int i, numPlayers, j/*, isUnique, potential*/;
  char *cardName = malloc(sizeof(char) * 15); //long enough for any card name

  /* Fill the Game State with garbage */
  for (i = 0; i < sizeof(struct gameState); i++){
    ((char*)G)[i] = floor(Random() * 256);
  }

  /* Set number of random players */
  numPlayers = floor(Random() * PLAYER_RANGE) + MIN_PLAYERS;
  if(printMode == 1){
    printf("Number of Players: %d\n", numPlayers);
  }

  /* Set random kingdom cards */
  /* i = 0; */
  /* isUnique = 1; */
  /* while(i < NUM_KINGDOM_CARDS){ */
  /*   potential = floor(Random() * KINGDOM_CARD_RANGE) + MIN_KINGDOM_CARD; */
  /*   for(j = 0; j < NUM_KINGDOM_CARDS; j++){ */
  /*     if(k[j] == potential){ */
  /* 	isUnique = 0; */
  /*     } */
  /*   } */
  /*   if(isUnique == 1){ */
  /*     k[i] = potential; */
  /*     printf("added %d\n", potential); */
  /*     i++; */
  /*   } */
  /* } */

  j = floor(Random() * KINGDOM_CARD_RANGE) + MIN_KINGDOM_CARD;
  for(i = 0; i < NUM_KINGDOM_CARDS; i++){
    k[i] = j;
    if(j < treasure_map){
      j++;
    }
    else { 
      j = MIN_KINGDOM_CARD;
    }
  }

  if(printMode == 1){
    printf("Kingdom Cards are: ");
    for(i = 0; i < NUM_KINGDOM_CARDS; i++){
      cardName = getCardName(k[i]);
      printf("%s, ", cardName);
    }
    printf("\n");
  }

  //initialize new game
  if(printMode == 1){
    printf("Initializing Game With:\n");
    printf("players = %d\n", numPlayers);
    for(i = 0; i < NUM_KINGDOM_CARDS; i++){
      printf("KingdomCard %d = %d\n", i, k[i]);
    }
    printf("seed = %d\n", seed);
  }

  if(initializeGame(numPlayers, k, seed, G) == -1){
    if(printMode == 1){
      printf("Intitialize Game Failed.\n");
    }
  }

  return numPlayers;
}


/*************************************
 * Function: printUsageStatement()   *
 * Input: No Arguments               *
 * Output: prints a usage statement  *
 *         to the console            *
 ************************************/
void printUsageStatement( /* No Args */){
  printf("Please Indicate the test you want to run.\n"\
	 "Do this by entering: testCoreUnit <test>.\n"\
	 "Valid options for <test> are:\n"\
	 "numHandCards\nendTurn\nisGameOver\nscoreFor\ngetCost\n\n");
}


/*************************************
 * Function: gameStateDiff()         *
 * Input: Two gameState references   *
 * Output: prints messages to the    *
 *         console describing        *
 *         differences in gameStates *
 ************************************/
int gameStateDiff(struct gameState *state1, struct gameState *state2){
  int i, j;
  
  //check number of players
  if(state1->numPlayers != state2->numPlayers){
    printf("Mismatch Number of Players\n");
    return 0;
  }
  //check supply counts
  for(i = 0; i < treasure_map + 1; i++){
    if(state1->supplyCount[i] != state2->supplyCount[i]){
      printf("Mismatch Number of SupplyCounts at %d\n", i);
      return 0;
    }
  }
  //check embargo tokens
  for(i = 0; i < treasure_map + 1; i++){
    if(state1->embargoTokens[i] != state2->embargoTokens[i]){
      printf("Mismatch Number of embargo tokens at %d\n", i);
      return 0;
    }
  }
  //check outpost played
  if(state1->outpostPlayed != state2->outpostPlayed){
    printf("Mismatch outpost played\n");
    return 0;
  }
  //check outpost turn
  if(state1->outpostTurn != state2->outpostTurn){
    printf("Mismatch outpost turn\n");
    return 0;
  }
  //check whose turn
  if(state1->whoseTurn != state2->whoseTurn){
    printf("Mismatch whose turn. state1: %d\t state2: %d\n", state1->whoseTurn, state2->whoseTurn);
    return 0;
  }
  // check phase
  if(state1->phase != state2->phase){
    printf("Mismatch Phase\n");
    return 0;
  }
  // check number of actions
  if(state1->numActions != state2->numActions){
    printf("Mismatch Number of Actions\n");
    return 0;
  }
  // check coins
  if(state1->coins != state2->coins){
    printf("Mismatch Coins: %d vs. %d\n", state1->coins, state2->coins);
    return 0;
  }
  // check number of buys
  if(state1->numBuys != state2->numBuys){
    printf("Mismatch Number of buys\n");
    return 0;
  }
  // check hand
  for(i = 0; i < MAX_PLAYERS; i++){
    for(j = 0; j < MAX_HAND; j++){
      if(state1->hand[i][j] != state2->hand[i][j]){
	printf("Mismatch Hand at player %d, card %d\n", i, j);
	return 0;
      }
    }
  }
  //check handCount
  for(i = 0; i < MAX_PLAYERS; i++){
    if(state1->handCount[i] != state2->handCount[i]){
      printf("Mismatch hand count at player %d\n", i);
      return 0;
    }
  }
  //check deck
  for(i = 0; i < MAX_PLAYERS; i++){
    for(j = 0; j < MAX_DECK; j++){
      if(state1->deck[i][j] != state2->deck[i][j]){
	printf("Mismatch Deck at player %d, deck %d\n", i, j);
	return 0;
      }
    }
  }
  //check deckCount
  for(i = 0; i < MAX_PLAYERS; i++){
    if(state1->deckCount[i] != state2->deckCount[i]){
      printf("Mismatch deck count at player %d\n", i);
      return 0;
    }
  }
  //check discard
  for(i = 0; i < MAX_PLAYERS; i++){
    for(j = 0; j < MAX_DECK; j++){
      if(state1->discard[i][j] != state2->discard[i][j]){
	printf("Mismatch Discard at player %d, deck %d\n", i, j);
	return 0;
      }
    }
  }
  //check discardCount
  for(i = 0; i < MAX_PLAYERS; i++){
    if(state1->discardCount[i] != state2->discardCount[i]){
      printf("Mismatch discard count at player %d\n", i);
      return 0;
    }
  }
  //check playedCards
  for(i = 0; i < MAX_DECK; i++){
    if(state1->playedCards[i] != state2->playedCards[i]){
      printf("Mismatch playedCards at deck %d\n", i);
      return 0;
    }
  }
  //check played Card Count
  if(state1->playedCardCount != state2->playedCardCount){
    printf("Mismatch Number of Played Card Count\n");
    return 0;
  }

  return 0;
}



